﻿using System;
using System.Collections.Generic;
using System.Text;
using OpenTK;
using System.Drawing;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System.IO;
using OpenTK.Math;
namespace Xeno.Core
{
    public class XenoEffect
    {
        private int _Geo;
        private int _Vertex;
        private int _Fragment;
        private int _Program;
        public bool HasGeo { get; private set; }
        public bool HasVertex { get; private set; }
        public bool HasFragment { get; private set; }
       
        public XenoEffect(string vertPath, string fragPath)
        {

            _Program = CreateProgram();
            if (vertPath != "")
            {
                _Vertex = CreateShader(vertPath, ShaderType.VertexShader);
                HasVertex = true;
            
            }
            if (fragPath != "")
            {
                _Fragment = CreateShader(fragPath, ShaderType.FragmentShader);
                HasFragment = true;
            }

                HasGeo = false;



         
            
            AttachShaders();
            LinkEffect();
        }

        ~XenoEffect()
        {
            /*
            if (HasGeo)
            {
                GL.DetachShader(_Program, _Geo);
                GL.DeleteShader(_Geo);
            }

            if (HasVertex)
            {
                GL.DetachShader(_Program, _Vertex);
                GL.DeleteShader(_Vertex);
            }
            if (HasFragment)
            {
                GL.DetachShader(_Program, _Fragment);
                GL.DeleteShader(_Fragment);
            }
            GL.DeleteProgram(_Program);
            */
        }

        public void LinkEffect()
        {
            GL.LinkProgram(_Program);
        }
        public void AttachShaders()
        {
            
            if(HasGeo) GL.AttachShader(_Program, _Geo);
            if (HasVertex) GL.AttachShader(_Program, _Vertex);
            if (HasFragment) GL.AttachShader(_Program, _Fragment);

        }
        public void SetInt(string name, int val)
        {
            GL.Uniform1(GL.GetUniformLocation(_Program, name), val);
        }
        public void SetFloat(string name, float val)
        {
            GL.Uniform1(GL.GetUniformLocation(_Program, name), val);
        }
        public void SetVec2(string name, Vector2 val)
        {
            GL.Uniform2(GL.GetUniformLocation(_Program, name), val);
        }
        public void SetVec3(string name, Vector3 val)
        {
            GL.Uniform3(GL.GetUniformLocation(_Program, name), val);
        }
        public void SetVec4(string name, Vector4 val)
        {
            GL.Uniform4(GL.GetUniformLocation(_Program, name), val);
        }
        public void SetMat4(string name, Matrix4 val,bool transpose)
        {
            GL.UniformMatrix4(GL.GetUniformLocation(_Program, name),transpose, ref val);
        }
        public void SetColor(string name, Color val)
        {
          
            SetVec4(name,new Vector4((float)val.R/255.0f,(float)val.G/255.0f,(float)val.B/255.0f,(float)val.A/255.0f));

        }
        public void Use()
        {
            GL.UseProgram(_Program);
        }
        public void Fin()
        {
            GL.UseProgram(0);
        }

        public static int CreateProgram()
        {
            int id = GL.CreateProgram();
            return id;
        }

        public static int CreateShader(string path, ShaderType type)
        {
            int id = GL.CreateShader(type);

            FileStream fs = new FileStream(path,FileMode.Open,FileAccess.Read);
            TextReader tr = new StreamReader(fs);

            GL.ShaderSource(id, @tr.ReadToEnd());

            GL.CompileShader(id);

            int status;
            GL.GetShader(id, ShaderParameter.CompileStatus, out @status);

            if (status == (int)OpenTK.Graphics.All.False)
            {

                string err = string.Empty;

                GL.GetShaderInfoLog(id,out err);
                XenoDebug.LogError("Effect Compile Error:" + err + "\nShaderType:" + type.ToString(),"XenoEffect.CreateShader");

            }

            return id;
        }

    }
}
